/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package negocio;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import javax.ejb.Stateless;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

/**
 *
 * @author Ing. Monica Merlo, Ing. Agustin  Fernandez
 */
@Stateless
public class GestorAppMovilBean implements GestorAppMovilRemote, GestorAppMovilLocal {
    static Logger logger = Logger.getLogger(GestorAppMovilBean.class);
    public static void log4j(Exception e){
        URL url = GestorAppMovilBean.class.getResource("/configuracion/log4j.properties");
        PropertyConfigurator.configure(url);
        logger.error(e);
    }

    /***
     * Método local que permite generar un jar con la app para el cel con el usuario y clave de logueo. Estas se insertan
     * dentro del manifiesto del jar.
     * @param usuario El usuario para agregar en el manifiesto
     * @param clave La clave para agregar en el manifiesto
     * @param fileJar El archivo que representa el jar
     * @param fileJad El archivo que representa el jad
     * @param fileDestino El archivo con el path donde se almacenaran fisicamente los archivos
     * @param fileManifest El archivo usado para poder recorrer el manifiesto del jar
     * @param url La url con la direccion donde estara almacenado el jar y la cual es agregada en el jad (para el atributo MIDlet-Jar-URL:)
     */
    public void generarJarParaDescarga(File fileJar, File fileJad, File fileManifest, File fileDestino, String url, String usuario, String clave) {
        try {
            String jartoEdit = fileJar.getPath();

            //Este es el nuevo archivo que quiero añadir dentro del jar
            String newFile = fileManifest.getPath();
            StringBuffer sbCopiaNewFile = new StringBuffer(newFile);
            sbCopiaNewFile.insert(sbCopiaNewFile.lastIndexOf("."), "Copia");
            File fCopiaManifest = new File(sbCopiaNewFile.toString());
            copiarArchivo(fileManifest, fCopiaManifest);
            agregarUsuarioClaveManifiesto(sbCopiaNewFile.toString(), usuario, clave);

            File tempJar = File.createTempFile("SiGeoJ2ME", null);
            JarFile jar = new JarFile(jartoEdit);
            JarOutputStream newJar = new JarOutputStream(new FileOutputStream(tempJar));

            byte buffer[] = new byte[1024];
            int bytesRead;

            FileInputStream fis = new FileInputStream(sbCopiaNewFile.toString());
            Enumeration entries = jar.entries();

            while (entries.hasMoreElements()) {
                JarEntry entry = (JarEntry) entries.nextElement();
                String name = entry.getName();

                if (name.contains("META-INF")) {
                    //No agrego el manifiesto al archivo
                    continue;
                }

                InputStream is = jar.getInputStream(entry);
                newJar.putNextEntry(entry);

                while ((bytesRead = is.read(buffer)) != -1) {
                    newJar.write(buffer, 0, bytesRead);
                }
            }

            try {
                //Agrego al nuevo jar la entrada con el manifiesto que será quien contiene la clave y usuario
                JarEntry entry = new JarEntry("META-INF/MANIFEST.MF");
                newJar.putNextEntry(entry);
                //Voy leyendo el nuevo manifiesto(con usuario y clave) y lo agrego al nuevo jar como una nueva
                //entrada
                while ((bytesRead = fis.read(buffer)) != -1) {
                    newJar.write(buffer, 0, bytesRead);
                }
            } finally {
                fis.close();
            }

            try {
                newJar.close();
            } catch (IOException ignorada) {
                GestorAppMovilBean.log4j(ignorada);
                //Ignoro la Excepción porque lo unico que hago aqui es intentar cerrar el archivo
            }
            try {
                jar.close();
            } catch (IOException ignorada) {
                GestorAppMovilBean.log4j(ignorada);
                //Ignoro la Excepción porque lo unico que hago aqui es intentar cerrar el archivo
            }

//            byte[] textBytes = usuario.getBytes();
//            MessageDigest md = MessageDigest.getInstance("MD5");
//            md.update(textBytes);
//            byte[] codigo = md.digest();
//            String usuarioMD5 = new String(codigo);

            File fileDestinoUsuario = new File(fileDestino.getParent() + File.separator + usuario, "SiGeoJ2ME.jar");
            File dirUsuario = new File(fileDestinoUsuario.getParent());
            dirUsuario.mkdirs();
            tempJar.renameTo(fileDestinoUsuario);
            String newFileJad = fileDestinoUsuario.getPath();
            StringBuffer sbCopiaNewFileJad = new StringBuffer(newFileJad);
            File fCopiaJad = new File(sbCopiaNewFileJad.substring(0, sbCopiaNewFileJad.lastIndexOf(".")) + ".jad");
            copiarModificarArchivoJAD(fileJad, fCopiaJad, url);
            fCopiaManifest.delete();

        } catch (Exception e) {
            GestorAppMovilBean.log4j(e);
        }
    }

    /***
     * Método local que permite generar un jar con la app para el cel con el usuario y clave de logueo. Estas se insertan
     * dentro del manifiesto del jar.
     * @param usuario El usuario para agregar en el manifiesto
     * @param clave La clave para agregar en el manifiesto
     * @param fileJar El archivo que representa el jar
     * @param fileJad El archivo que representa el jad
     * @param fileDestino El archivo con el path donde se almacenaran fisicamente los archivos
     * @param fileManifest El archivo usado para poder recorrer el manifiesto del jar
     * @param url La url con la direccion donde estara almacenado el jar y la cual es agregada en el jad (para el atributo MIDlet-Jar-URL:)
     */
    public void generarJarParaDescargaRemote(File fileJar, File fileJad, File fileManifest, File fileDestino, String url, String usuario, String clave) {
        try {
            String jartoEdit = fileJar.getPath();

            //Este es el nuevo archivo que quiero añadir dentro del jar
            String newFile = fileManifest.getPath();
            StringBuffer sbCopiaNewFile = new StringBuffer(newFile);
            sbCopiaNewFile.insert(sbCopiaNewFile.lastIndexOf("."), "Copia");
            File fCopiaManifest = new File(sbCopiaNewFile.toString());
            copiarArchivo(fileManifest, fCopiaManifest);
            agregarUsuarioClaveManifiesto(sbCopiaNewFile.toString(), usuario, clave);

            File tempJar = File.createTempFile("SiGeoJ2ME", null);
            JarFile jar = new JarFile(jartoEdit);
            JarOutputStream newJar = new JarOutputStream(new FileOutputStream(tempJar));

            byte buffer[] = new byte[1024];
            int bytesRead;

            FileInputStream fis = new FileInputStream(sbCopiaNewFile.toString());
            Enumeration entries = jar.entries();

            while (entries.hasMoreElements()) {
                JarEntry entry = (JarEntry) entries.nextElement();
                String name = entry.getName();

                if (name.contains("META-INF")) {
                    //No agrego el manifiesto al archivo
                    continue;
                }

                InputStream is = jar.getInputStream(entry);
                newJar.putNextEntry(entry);

                while ((bytesRead = is.read(buffer)) != -1) {
                    newJar.write(buffer, 0, bytesRead);
                }
            }

            try {
                //Agrego al nuevo jar la entrada con el manifiesto que será quien contiene la clave y usuario
                JarEntry entry = new JarEntry("META-INF/MANIFEST.MF");
                newJar.putNextEntry(entry);
                //Voy leyendo el nuevo manifiesto(con usuario y clave) y lo agrego al nuevo jar como una nueva
                //entrada
                while ((bytesRead = fis.read(buffer)) != -1) {
                    newJar.write(buffer, 0, bytesRead);
                }
            } finally {
                fis.close();
            }

            try {
                newJar.close();
            } catch (IOException ignorada) {
                GestorAppMovilBean.log4j(ignorada);
                //Ignoro la Excepción porque lo unico que hago aqui es intentar cerrar el archivo
            }
            try {
                jar.close();
            } catch (IOException ignorada) {
                GestorAppMovilBean.log4j(ignorada);
                //Ignoro la Excepción porque lo unico que hago aqui es intentar cerrar el archivo
            }

//            byte[] textBytes = usuario.getBytes();
//            MessageDigest md = MessageDigest.getInstance("MD5");
//            md.update(textBytes);
//            byte[] codigo = md.digest();
//            String usuarioMD5 = new String(codigo);

            File fileDestinoUsuario = new File(fileDestino.getParent() + File.separator + usuario, "SiGeoJ2ME.jar");
            File dirUsuario = new File(fileDestinoUsuario.getParent());
            dirUsuario.mkdirs();
            tempJar.renameTo(fileDestinoUsuario);
            String newFileJad = fileDestinoUsuario.getPath();
            StringBuffer sbCopiaNewFileJad = new StringBuffer(newFileJad);
            File fCopiaJad = new File(sbCopiaNewFileJad.substring(0, sbCopiaNewFileJad.lastIndexOf(".")) + ".jad");
            copiarModificarArchivoJAD(fileJad, fCopiaJad, url);
            fCopiaManifest.delete();
        } catch (Exception e) {
            GestorAppMovilBean.log4j(e);
        }
    }

    /***
     * Método que llama al método borrarDirectorio para eliminar el directorio con las descargas del usuario, una
     * vez que este realizo dichas descargas
     * @param directorioUsuario el directorio a borrar
     */
    public void eliminarDirectorioUsuario(File directorioUsuario){
        try{
            this.borrarDirectorio(directorioUsuario);
        }catch (Exception e){
            GestorAppMovilBean.log4j(e);
        }
    }

    /***
     * Método que llama al método borrarDirectorio para eliminar el directorio con las descargas del usuario, una
     * vez que este realizo dichas descargas
     * @param directorioUsuario el directorio a borrar
     */
    public void eliminarDirectorioUsuarioRemote(File directorioUsuario){
        try{
            this.borrarDirectorio(directorioUsuario);
        }catch (Exception e){
            GestorAppMovilBean.log4j(e);
        }
    }

    /***
     * Método que permite agregar fisicamente el usuario y clave en el archivo del manifiesto que ya existe.
     * @param urlAppMovil  La url donde se encuentra la app del celular
     * @param usuario El usuario para agregar en el manifiesto
     * @param clave La clave para agregar en el manifiesto
     * @throws Exception Tira la Excepción hacia el método desde donde se lo llama a este método.
     */
    private void agregarUsuarioClaveManifiesto(String urlAppMovil, String usuario, String clave) throws Exception {
        BufferedWriter bw = new BufferedWriter(new FileWriter(urlAppMovil, true));
        bw.write("UsuarioSigeo: " + usuario);
        bw.newLine();
        bw.write("ClaveSigeo: " + clave);
        bw.flush();
        bw.close();
    }

    private void copiarModificarArchivoJAD(File src, File dst, String url) throws IOException {
        BufferedReader in = new BufferedReader(new FileReader(src));
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dst));

        String linea = in.readLine();
        StringBuffer sb = new StringBuffer();
        while(linea!=null){
            sb.append(linea+"\n");
            linea=in.readLine();
        }
        if (sb.indexOf("MIDlet-Jar-URL:") != -1) {
            sb = sb.insert(sb.indexOf("MIDlet-Jar-URL:") + 16, url);
        }
        byte[] buf = sb.toString().getBytes();
        int len = buf.length;
        out.write(sb.toString().getBytes(), 0, len);
        in.close();
        out.flush();
        out.close();
    }

    private void copiarArchivo(File src, File dst) throws IOException {
        BufferedInputStream in = new BufferedInputStream(new FileInputStream(src));
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dst));

        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0) {
            String buff = new String(buf);
            if(buff.contains("MIDlet-Jar-URL:")){
                buff = buff.substring(0, buff.indexOf(":"));

//                buff.
            }
            out.write(buf, 0, len);
        }
        in.close();
        out.flush();
        out.close();
    }

    private boolean borrarDirectorio(File directorioUsuario) {
        File[] files = directorioUsuario.listFiles();
        for (int i = 0; i < files.length; i++) {
            if (files[i].isDirectory()) {
                this.borrarDirectorio(files[i]);
            } else {
                files[i].delete();
            }
        }
        return directorioUsuario.delete();
    }

    
}
